package com.example.fivechesss;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Point;
import android.os.Bundle;
import android.os.Parcelable;
import android.os.PersistableBundle;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.widget.TextView;
import android.widget.Toast;

import java.util.ArrayList;

/**
 * Created by Administrator on 2016/9/18 0018.
 */
public class ChessBoardView extends View {
    private static final String TAG ="ChessBoardView" ;
    // 棋盘的宽度，也是长度
    private int mViewWidth;
    // 棋盘每格的长度
    private float maxLineHeight;
    private Paint paint = new Paint();
    // 定义黑白棋子的Bitmap
    private Bitmap mwhitePiece, mblackPiece;
    private float ratioPieceOfLineHeight = 1 * 1.0f /2;

    // 判断当前落下的棋子是否是白色的
    private boolean mIsWhite = true;
    // 记录黑白棋子位置的列表
    private ArrayList<Point> mwhiteArray = new ArrayList<>();
    private ArrayList<Point> mblackArray = new ArrayList<>();

    // 游戏是否结束
    private boolean mIsGameOver;
    // 游戏结束，是否是白色方胜利
    private boolean mIsWhiteWinner;
    //执行顺序：onMeasure>onSizeChanged>onDraw
    public ChessBoardView(Context context) {
        super(context);
        init();
    }

    public ChessBoardView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    public ChessBoardView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }

    /**
     * 初始化画笔
     */
    private void init() {
        //设置画笔颜色，此时会比默认显示浅一点。
        paint.setColor(0x88000000);
        //抗锯齿
        paint.setAntiAlias(true);
        //防抖动
        paint.setDither(true);
        //设置填充样式，如果不设置，默认全部填充（FILL），另外样式：1.Paint.Style.STROKE：描边 2.Paint.Style.FILL_AND_STROKE：描边并填充
        paint.setStyle(Paint.Style.STROKE);
        mwhitePiece = BitmapFactory.decodeResource(getResources(), R.mipmap.white);
        mblackPiece = BitmapFactory.decodeResource(getResources(), R.mipmap.black);
    }

    /**
     * 测量view大小，使形成正方形。
     * @param widthMeasureSpec
     * @param heightMeasureSpec
     */
    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        int widthSize=MeasureSpec.getSize(widthMeasureSpec);
        int heighSize=MeasureSpec.getSize(heightMeasureSpec);
        int width=Math.min(widthSize,heighSize);
        setMeasuredDimension(width,width);//设置view的大小。
        Log.e(TAG,"onMeasure");
    }

    /**
     * 当view发生变化时候回调。此方法作用是在init时创建位图的基础上创建了一个新的位图
     * @param w
     * @param h
     * @param oldw
     * @param oldh
     */
    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        //棋盘宽度/也是长度，此处w和上面onMeasure中width值是相同的、
        mViewWidth = w;
        //棋盘每格的长度，高度
        maxLineHeight = mViewWidth * 1.0f / Constants.MAX_LINE;//Constants.MAX_LINE指的是棋盘行数，列数。
        //棋子的长宽。
        int pieceWidth = (int) (maxLineHeight * ratioPieceOfLineHeight);
        //第一个参数是待修改的Bitmap,第二第三个参数分别为修改后的宽、高，最后一个Boolean参数暂时不知什么作用。
        //createScaledBitmap：根据原来的位图创建一个新的位图。此时设置新位图长宽都是单元格长宽的二分之一。
        mwhitePiece = Bitmap.createScaledBitmap(mwhitePiece, pieceWidth, pieceWidth, false);
        mblackPiece = Bitmap.createScaledBitmap(mblackPiece, pieceWidth, pieceWidth, false);
        Log.e(TAG,"onSizeChanged");
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        if (mIsGameOver) {//判断游戏是否结束，
            return false;//如果判断游戏已经结束，则返回false，touch事件响应终止。在放置棋子也无显示。
        }
        int action=event.getAction();
        if (action==MotionEvent.ACTION_UP) {
            int x= (int) event.getX();//得到点击处距离子view左边距离
            int y= (int) event.getY();//得到点击处距离子view右边距离
            Point point = getValidPoint(x, y);
            if (mwhiteArray.contains(point) || mblackArray.contains(point)) {
                Toast.makeText(getContext(), "请勿重复落子！", Toast.LENGTH_SHORT).show();
                return false;
            }
            if (mIsWhite) {
                mwhiteArray.add(point);//添加到白色数组
                MainActivity.setTextView();//更新提示文字
            } else {
                mblackArray.add(point);
                MainActivity.setTextView();//更新提示文字
            }
            invalidate();//刷新UI
            mIsWhite = !mIsWhite;//取反
        }
        Log.e(TAG,"onTouchEvent");
        return true;
    }

    /**
     * 得到已经设置好的点。此处是point不是paint。
     * Point（）可以存储位置信息，分别为x，y。为android提供的类
     * @param x
     * @param y
     * @return
     */
    private Point getValidPoint(int x, int y) {
        int validX = (int) (x / maxLineHeight);//通过点击位置除以单元格长度，然后取整，得到在第几个单元格处
        int validY = (int) (y / maxLineHeight);//通过点击位置除以单元格长度，然后取整，得到在第几个单元格处
        //二者交叉，得到具体位置。
        return new Point(validX, validY);
    }
    /**
     * 绘制棋盘
     * @param canvas
     */
    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        // 绘制棋盘的网格
        drawBoard(canvas);
        // 绘制棋盘的黑白棋子
        drawPieces(canvas);
        // 检查游戏是否结束
        checkGameOver();
        Log.e(TAG,"onDraw");
    }
    /**
     *     绘制棋盘的网线
     */
    private void drawBoard(Canvas canvas) {
        int w = mViewWidth;//棋盘长宽
        float lineHeight = maxLineHeight;//单元格的长宽
        for (int i = 0; i < Constants.MAX_LINE; i++) {
            int startX = (int) (lineHeight / 2);
            int endX = (int) (w - lineHeight / 2);
            int y = (int) ((0.5 + i) * lineHeight);
            Log.e(TAG,startX+" "+endX+" "+y);
            canvas.drawLine(startX, y, endX, y, paint);//左右的线，左右开始结尾值一样，只是改变上下即可，左上右下
            canvas.drawLine(y, startX, y, endX, paint);//上下的线，同上理可知。
        }
    }
    /**
     *  根据黑白棋子的数组绘制棋子
     */
    private void drawPieces(Canvas canvas) {
        for (int i = 0, n = mwhiteArray.size(); i < n; i++) {//mwhiteArray:记录白色棋子位置的列表。
            Point whitePoint = mwhiteArray.get(i);//得到数组中对应索引的位置对象。
            float left = (whitePoint.x + 3/5) * maxLineHeight;
            float top = (whitePoint.y + 3/5) * maxLineHeight;
            canvas.drawBitmap(mwhitePiece, left, top, null);
        }

        for (int i = 0, n = mblackArray.size(); i < n; i++) {
            Point blackPoint = mblackArray.get(i);
            float left = (blackPoint.x + (1 - ratioPieceOfLineHeight) / 2) * maxLineHeight;
            float top = (blackPoint.y + (1 - ratioPieceOfLineHeight) / 2) * maxLineHeight;
            canvas.drawBitmap(mblackPiece, left, top, null);
        }
    }

    /**
     * 检查游戏是否结束
     */
    private void checkGameOver() {
        CheckWinner checkWinner = new CheckWinner();
        boolean whiteWin = checkWinner.checkFiveInLineWinner(mwhiteArray);
        boolean blackWin = checkWinner.checkFiveInLineWinner(mblackArray);

        if (whiteWin || blackWin) {
            mIsGameOver = true;
            mIsWhiteWinner = whiteWin;
            String text = mIsWhiteWinner ? "白棋胜利" : "黑棋胜利";
            Toast.makeText(getContext(), text, Toast.LENGTH_SHORT).show();
        }
    }

    /**
     * 再来一局
     */
//    public  void start() {
//        mwhiteArray.clear();
//        mblackArray.clear();
//        mIsGameOver = false;
//        mIsWhiteWinner = false;
//        postInvalidate();
////        invalidate();
//    }



    /**
     //     * 恢复残局
     //     * @param state
     //     */
//    @Override
//    protected void onRestoreInstanceState(Parcelable state) {
//        if (state instanceof Bundle) {
//            Bundle bundle = (Bundle) state;
//            mIsGameOver = bundle.getBoolean(INSTANCE_GAME_OVER);
//            mwhiteArray = bundle.getParcelableArrayList(INSTANCE_WHITE_ARRAY);
//            mblackArray = bundle.getParcelableArrayList(INSTANCE_BLACK_ARRAY);
//            super.onRestoreInstanceState(bundle.getParcelable(INSTANCE));
//            return;
//        }
//        super.onRestoreInstanceState(state);
//    }
//
//    /**
//     * 保存残局
//     * @return
//     */
//    @Override
//    protected Parcelable onSaveInstanceState() {
//        Bundle bundle = new Bundle();
//        bundle.putParcelable(INSTANCE, super.onSaveInstanceState());
//        bundle.putBoolean(INSTANCE_GAME_OVER, mIsGameOver);
//
//        bundle.putParcelableArrayList(INSTANCE_BLACK_ARRAY, mblackArray);
//        bundle.putParcelableArrayList(INSTANCE_WHITE_ARRAY, mwhiteArray);
//        return bundle;
//    }
}
